from area_keywords import AreaItem, AreaKeywords
from typing import List, Tuple, Optional
import dbutil


class AddressMatch:
    def __init__(self):
        self.area2 = AreaKeywords()
        self.area3 = AreaKeywords()
        self.area4 = AreaKeywords()
        self.area5 = AreaKeywords()
        self.areaNames = {}  # 存储从数据库加载的地址库

    def load_keywords(self) -> None:
        """加载各级别区域关键词"""
        self.area2.load_keywords(level=2)
        self.area3.load_keywords(level=3)
        self.area4.load_keywords(level=4)
        self.area5.load_keywords(level=5)
        """从数据库加载地址库并初始化地址匹配器"""
        # 构建查询SQL
        sql = """
        select code, std_name  from area2_feature
        union all select code, full_name as std_name from area3_feature
        union all select code, full_name as std_name from area4_feature
        union all select code, full_name as std_name from area5_feature
        """

        # 执行查询获取地址数据
        rows = dbutil.query_rows(sql, ())

        # 将结果存储到areaNames字典中
        for row in rows:
            code = row['code']
            name = row['std_name']
            self.areaNames[code] = name

    def get_valid_matches(self, in_area_code, address: str) -> List[
        Tuple[Optional[AreaItem], Optional[AreaItem], Optional[AreaItem], Optional[AreaItem]]]:
        """获取合法的地址匹配项"""
        # 获取各层级匹配结果
        area2_list = []
        if len(in_area_code) >= 4:  # 65XX , 65XXYY
            area2_list = [AreaItem(in_area_code[0:4], '')]
        else:
            area2_list = self.area2.match(address) + [None]

        if len(in_area_code) >= 6:  # 65XXYY
            area3_list = [AreaItem(in_area_code[0:6], '')]
        else:
            area3_list = self.area3.match(address) + [None]

        area4_list = self.area4.match(address) + [None]
        area5_list = self.area5.match(address) + [None]

        # 生成所有可能的组合
        match_list = []
        for a2 in area2_list:
            for a3 in area3_list:
                for a4 in area4_list:
                    for a5 in area5_list:
                        match_list.append((a2, a3, a4, a5))

        # 过滤规则1：前面的code必须是后面非空code的前缀
        valid_matches = []
        for match in match_list:
            valid = True
            codes = [item.code if item else None for item in match]

            for i in range(len(codes)):
                if codes[i] is None:
                    continue
                for j in range(i + 1, len(codes)):
                    if codes[j] is not None and not codes[j].startswith(codes[i]):
                        valid = False
                        break
                if not valid:
                    break
            if valid:
                valid_matches.append(match)

        # 过滤规则2：前面关键词出现位置必须小于后面关键词出现位置
        final_matches = valid_matches
        """
        for match in valid_matches:
            valid = True
            positions = []
            
            # 获取每个非空项的关键词在地址中的位置
            for item in match:
                if item:
                    pos = address.find(item.keyword)
                    if pos == -1:  # 关键词不在地址中，视为无效
                        valid = False
                        break
                    positions.append((pos, item))
                else:
                    positions.append((None, None))
            
            if not valid:
                continue
            
            # 检查位置顺序
            for i in range(len(positions)):
                if positions[i][0] is None:
                    continue
                for j in range(i + 1, len(positions)):
                    if positions[j][0] is not None and positions[i][0] >= positions[j][0]:
                        valid = False
                        break
                if not valid:
                    break
            if valid:
                final_matches.append(match)
        """

        return final_matches

    def format_std_name(self, area_name, short_name):
        if short_name == '{乡镇政府}':
            if area_name.endswith('乡') or area_name.endswith('镇'):
                return f'{area_name}政府'
            elif area_name.endswith('街道'):
                return f'{area_name}办事处'
            elif area_name.endswith('管委会'):
                return f'{area_name}'
            else:
                return f'{area_name}政府'
        return f'{area_name}{short_name}'

    def get_level_of_code(self, area_code):
        addr_level = 1
        if len(area_code) == 2:
            addr_level = 1
        elif len(area_code) == 4:
            addr_level = 2
        elif len(area_code) == 6:
            addr_level = 3
        elif len(area_code) == 9:  # 乡镇，村
            addr_level = 4
        elif len(area_code) > 9:
            addr_level = 5
        return addr_level

    def get_address_name(self, area_code, addr_level=None):

        if addr_level is None:
            if len(area_code) == 2:
                addr_level = 1
            elif len(area_code) == 4:
                addr_level = 2
            elif len(area_code) == 6:
                addr_level = 3
            elif len(area_code) >= 9:  # 乡镇，村
                addr_level = 4

        # 提取不同级别的code
        code2 = area_code[0:4] if len(area_code) >= 4 else ''
        code3 = area_code[0:6] if len(area_code) >= 6 else ''
        code4 = area_code[0:9] if len(area_code) >= 9 else ''

        # 获取各级地址名称
        addr2 = self.areaNames.get(code2, '') if code2 else ''
        addr3 = self.areaNames.get(code3, '') if code3 else ''
        addr4 = self.areaNames.get(code4, '') if code4 else ''
        # 调整各级地址名称，县级除某某区外其他均不用加前缀，乡，村级同理
        if addr_level == 1:
            return '自治区'
        elif addr_level == 2:
            return f"{addr2}"
        elif addr_level == 3:
            return self.get_provincial_level_address_name(addr2, addr3)
        elif addr_level >= 4:
            return self.get_township_level_address_name(addr2, addr3, addr4)
        else:
            return ''

    def get_provincial_level_address_name(self, addr2, addr3):
        if '区' in addr3:
            return f"{addr2}{addr3}"
        else:
            return f"{addr3}"

    def get_township_level_address_name(self, addr2, addr3, addr4):
        if '区' in addr3:
            return f"{addr2}{addr3}{addr4}"
        else:
            return f"{addr3}{addr4}"

    def get_best_match_tuples(self, in_area_code, address: str) -> Tuple[
        Optional[AreaItem], Optional[AreaItem], Optional[AreaItem], Optional[AreaItem]]:
        # 去掉后缀00

        if in_area_code.endswith("00"):
            in_area_code = in_area_code[:-2]
        if in_area_code.endswith("00"):
            in_area_code = in_area_code[:-2]

        """获取最佳匹配项"""
        match_list = self.get_valid_matches(in_area_code, address)
        if not match_list:
            return (None, None, None, None)

        # 使用sorted()并指定key函数进行排序，而不是list.sort()
        def sort_key(match):
            """排序键函数：先按匹配度降序，再按优先级降序"""
            # 计算匹配度：非空项的数量
            score1 = sum(1 for item in match if item is not None)
            score2 = sum(len(item.keyword) for item in match if item is not None)
            # 计算优先级：area4和area3不为空时优先
            priority = 0
            if match[2] is not None:  # area4item
                priority += 1
            if match[1] is not None:  # area3item
                priority += 4
            # 返回负值以便实现降序排序
            return (-score1, -priority, -score2)

        # 使用sorted函数和自定义key进行排序
        sorted_matches = sorted(match_list, key=sort_key)

        # 返回最佳匹配
        return sorted_matches[0]

    def get_best_match(self, in_area_code, address: str):
        area2, area3, area4, area5 = self.get_best_match_tuples(in_area_code, address)
        addr_level = 0
        addr_code = ''
        if area5 is not None:
            addr_level = 5
            addr_code = area5.code
        elif area4 is not None:
            addr_level = 4
            addr_code = area4.code
        elif area3 is not None:
            addr_level = 3
            addr_code = area3.code
        elif area2 is not None:
            addr_level = 2
            addr_code = area2.code
        else:
            addr_level = 1
            addr_code = '65'
        return addr_code


# 测试代码
if __name__ == "__main__":
    # 初始化并加载关键词
    addr_match = AddressMatch()
    addr_match.load_keywords()

    # 测试地址
    test_address = "白碱滩区委组织部"

    best_match = addr_match.get_best_match("", test_address)
    print("\n最佳匹配:")
    print(f"  {best_match}")

    print('name:', addr_match.get_address_name(str(best_match), None))
